﻿using DimensionsHelper.Common.Contracts.Excel;
using DimensionsHelper.Common.Contracts.Excel.Options;

namespace DimensionsHelper.Client.WinUi.ViewModels;

public partial class QueryDataTableViewModel(
    DataTable dataSource,
    ObservableCollection<QueryDataTableViewModel> collection) : ObservableObject
{
    private readonly DataTable _dataSource = dataSource;


    [ObservableProperty]
    public partial string TableName { get; set; } = string.Empty;


    [ObservableProperty]
    public partial string Metadata { get; set; } = string.Empty;


    [ObservableProperty]
    public partial string Casedata { get; set; } = string.Empty;


    [ObservableProperty]
    public partial string Query { get; set; } = "未设置";


    public StringMapCollection DataSource { get; } = StringMap.BuildCollection(dataSource);


    [RelayCommand]
    private async Task ExportData()
    {
        if (_dataSource.Columns.Count == 0 || _dataSource.Rows.Count == 0)
        {
            await App.GetService<IMessageService>()
                .ShowAsync(ResourceKeys.AppSqlQueryResultIsEmpty.GetLocalized(), null);
            return;
        }

        string? file = await App.GetService<IFilePikerService>()
            .SaveFileAsync(FileFilters.Excel);

        if (string.IsNullOrEmpty(file))
        {
            return;
        }

        if (File.Exists(file))
        {
            File.Delete(file);
        }

        IExcelWorkbookOperator excel = App.GetService<IExcelWorkbookOperator>();
        excel.Create(file);

        IProjectTask task = QueryViewModel.GetProjectTask();

        try
        {
            IExcelWorksheetOperator sheet = excel.GetWorksheet("VDATA");

            // Header
            object[,] header = new object[1, _dataSource.Columns.Count];
            for (int i = 0; i < _dataSource.Columns.Count; i++)
            {
                header[0, i] = _dataSource.Columns[i].ColumnName;
            }

            IExcelRangeOperator headerRange = sheet.GetRange(1, 1, 1, header.Length);
            headerRange.Value = header;
            headerRange.SetStyle(new RangeStyleOptions
            {
                Font = new FontStyleOptions
                {
                    FontType = FontType.Bold
                },
                VAlign = ExcelVAlign.Center,
                InteriorColor = Colors.LightGray.ToExcelStyleColor()
            });

            // Data
            object[,] dataArray = new object[_dataSource.Rows.Count, _dataSource.Columns.Count];

            for (int i = 0; i < _dataSource.Rows.Count; i++)
            {
                for (int j = 0; j < _dataSource.Columns.Count; j++)
                {
                    object value = _dataSource.Rows[i][j];

                    if (value is string str)
                    {
                        if (int.TryParse(str, out int integer))
                        {
                            value = integer;
                        }
                        else if (double.TryParse(str, out double db))
                        {
                            value = db;
                        }
                    }

                    dataArray[i, j] = value;
                }
            }

            sheet.GetRange(2, 1, _dataSource.Rows.Count + 1, _dataSource.Columns.Count)
                .Value = dataArray;
            excel.Save();

            if (Path.GetDirectoryName(file) is { } dir)
            {
                task.Directory(dir,
                    ResourceKeys.AppDirectoryExportSuccessfullyMessage.GetLocalized(),
                    dir);
            }

            task.Directory(file,
                ResourceKeys.AppFileExportSuccessfullyMessage.GetLocalized(),
                file);
        }
        catch (Exception e)
        {
            task.Error(e.Message);
        }
        finally
        {
            excel.Close();

            App.GetService<INavigationService>().NavigateTo(
                typeof(TaskInformationViewModel).FullName!,
                QueryViewModel.GetProjectTask().Id);
        }
    }


    [RelayCommand]
    private void Remove() => collection.Remove(this);
}